﻿using FineUICoreDesigner;
using FineUICoreDesigner.Base;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace FineUIDesignerVSIX.Handle
{
    /// <summary>
    /// 生成designer.cs
    /// </summary>
    public class RazorPageDesignerHandle : IRazorPageAfterSave
    {
        /// <summary>
        /// 不生成的标记
        /// </summary>
        public const string NoWebForms = "NoWebForms";

        public const string Target = "<f:([a-zA-Z]+)[^>]+\\bID=\"([a-zA-Z0-9_]+)\"[^>]*>";
        public const string TargetNameof = "<f:([a-zA-Z]+)[^>]*ID=\"@nameof\\(([\\w\\.]+)\\)\"[^>]*>";

        /// <summary>
        /// 按模板生成文件
        /// </summary>
        /// <param name="editFileInfo"></param>
        /// <exception cref="NotImplementedException"></exception>
        public void Handle(RazorPageFileInfo editFileInfo)
        {
            if (Regex.Match(editFileInfo.FileContent, $"// *{BaseHelp.NoFineUIDesigner}").Success) return;
            if (Regex.Match(editFileInfo.FileContent, $"// *{NoWebForms}").Success) return;
            if (!BaseHelp.Config.FineUIDesigner) return;
            /*
             * 如果存在标识就返回
             * 得到当前页面所有控件的ID 和 类型
             * 生成内容
             * 保存
             * **/
            List<TargetInfo> tarList = GetTargetList(editFileInfo);
            string content = GenerateDesignerClassContent(editFileInfo, tarList);
            if (!string.IsNullOrEmpty(content) && tarList.Any())
            {
                BaseHelp.WriteAllText(editFileInfo.DesignerFilePath, content);
                BaseHelp.OutputLine($"生成 {editFileInfo.DesignerFileName} 成功 ✏️");
            }
        }

        private string GenerateDesignerClassContent(RazorPageFileInfo editFileInfo, List<TargetInfo> tarList)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine($"//------------------------------------------------------------------------------");
            sb.AppendLine("//     这段代码是由没想好生成的。");
            sb.AppendLine("//     对这个文件的更改可能导致不正确的行为，并且如果代码重新生成，这些更改会丢失.");
            sb.AppendLine($"//     在 .cshtml 文件中添加 //{BaseHelp.NoFineUIDesigner} 注释，以防止生成此文件。");
            sb.AppendLine($"//     或者在 appsettings 中添加 FineUIDesigner:false，以防止生成此文件。");
            sb.AppendLine("//------------------------------------------------------------------------------");
            sb.AppendLine($"namespace {editFileInfo.NamespaceName}");
            sb.AppendLine("{");
            sb.AppendLine($"   public partial class {editFileInfo.ClassName}");
            sb.AppendLine("   {");
            foreach (var item in tarList)
            {
                sb.AppendLine($"       /// <summary>");
                sb.AppendLine($"       /// {item.Type}");
                sb.AppendLine($"       /// </summary>");
                sb.AppendLine($"       protected FineUICore.{item.Type}AjaxHelper {item.ID} => UIHelper.Button(\"{item.ID}\");");
                sb.AppendLine($"      ");
            }
            sb.AppendLine("   }");
            sb.AppendLine("}");
            return sb.ToString();
        }

        private List<TargetInfo> GetTargetList(RazorPageFileInfo editFileInfo)
        {
            List<TargetInfo> tarList = new List<TargetInfo>();
            foreach (Match match in Regex.Matches(editFileInfo.FileContent, Target))
            {
                if (match.Success && match.Groups.Count == 3)
                {
                    string type = match.Groups[1].ToString();
                    string id = match.Groups[2].ToString();
                    if (type == "ContentPanel")
                        type = "Panel";
                    tarList.Add(new TargetInfo() { ID = id, Type = type });
                }
            }
            foreach (Match match in Regex.Matches(editFileInfo.FileContent, TargetNameof))
            {
                if (match.Success && match.Groups.Count == 3)
                {
                    string type = match.Groups[1].ToString();
                    string nameofExpression = match.Groups[2].ToString();
                    var syntaxTree = CSharpSyntaxTree.ParseText(nameofExpression);
                    var root = syntaxTree.GetRoot() as CompilationUnitSyntax;
                    var memberAccess = root.DescendantNodes().OfType<MemberAccessExpressionSyntax>().FirstOrDefault();
                    // Extract the identifier from the MemberAccessExpressionSyntax node
                    var id = memberAccess.Name.Identifier.Text;
                    if (type == "ContentPanel")
                        type = "Panel";
                    tarList.Add(new TargetInfo() { ID = id, Type = type });
                }
            }
            return tarList;
        }
    }
}
